package lv.rtu.ditf.dc.url;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;

import lv.rtu.ditf.dc.stream.StringStreamReader;

/**
 * 
 * @author Pāvels Koliškins, Edgars Matisāns
 *
 */
public class URLDocumentLoader {
	/**
	 * Default connection timeout in milliseconds.
	 */
	public static final int DEFAULT_CONNECT_TIMEOUT = 30000;
	
	private static Set<String> supportedContentTypes;
	static {
		supportedContentTypes = new HashSet<String>();
		supportedContentTypes.add("text/html");
	}
	
	private final String pageUrl;
	private final int connectionTimeout;
	
	public URLDocumentLoader(String pageUrl) {
		this(pageUrl, DEFAULT_CONNECT_TIMEOUT);
	}
	
	public URLDocumentLoader(String pageUrl, int connectionTimeout) {
		this.pageUrl = pageUrl;
		this.connectionTimeout = connectionTimeout;
	}
	
	public URLDocument loadDocument() throws MalformedURLException, IOException, UnsupportedContentTypeException {
		URL url = new URL(pageUrl);
		URLConnection conn = url.openConnection();
		conn.setConnectTimeout(connectionTimeout);
		
		InputStream inStream = null;
		try {
			inStream = conn.getInputStream();
			BufferedInputStream buffInStream = new BufferedInputStream(inStream);
			
			String contentType = getContentType(conn, buffInStream);
			if (contentType == null)
				throw new UnsupportedContentTypeException(pageUrl);
			
			String content = getContent(conn, buffInStream);
			
			URLDocument doc = new URLDocument(content, contentType);
			return doc;
		}
		catch (IOException ex) {
			throw ex;
		}
		finally {
			if (inStream != null)
				inStream.close();
		}
	}

	private String getContentType(URLConnection conn, InputStream inStream) throws IOException {
		String contentType;
		
		contentType = conn.getContentType();
		if (contentType == null)
			contentType = URLConnection.guessContentTypeFromStream(inStream);
		
		if (contentType != null) {
			if (supportedContentTypes.contains(contentType))
				return contentType;
			
			for (String allowedContentType : supportedContentTypes) {
				if (allowedContentType.contains(contentType) || contentType.contains(allowedContentType))
					return contentType;
			}
		}
		
		return null;
	}
	
	private String getContent(URLConnection conn, InputStream inStream) throws IOException {
		String encoding = conn.getContentEncoding();
		
		return StringStreamReader.read(inStream, encoding);
	}
}